using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing.Design;
using System.Windows.Forms;
using System.Windows.Forms.Design;
using System.ComponentModel;
using System.Security.Permissions;

namespace VSSDKAssist.Assets.Editors
{
	/// <summary>
	/// Base ListView editor class
	/// </summary>
	public abstract class ListViewEditorBase : UITypeEditor, IDisposable
	{
		#region Fields
		private bool disposed;
		#endregion

		private ListView control;

		/// <summary>
		/// Gets or sets the control.
		/// </summary>
		/// <value>The control.</value>
		protected ListView Control
		{
			get
			{
				return this.control;
			}
			set 
			{
				this.control = value;
			}
		}

		private IWindowsFormsEditorService windowsFormsEditorService;

		/// <summary>
		/// Gets or sets the windows forms editor service.
		/// </summary>
		/// <value>The windows forms editor service.</value>
		protected IWindowsFormsEditorService WindowsFormsEditorService
		{
			get
			{
				return this.windowsFormsEditorService;
			}
			set
			{
				this.windowsFormsEditorService = value;
			}
		}

		#region Constructors
		/// <summary>
		/// Initializes a new instance of the <see cref="ListViewEditorBase"/> class.
		/// </summary>
		protected ListViewEditorBase()
		{
			this.Control = new ListView();
			this.Control.MultiSelect = false;
			this.Control.SelectedIndexChanged += new EventHandler(ControlSelectedIndexChanged);
			this.Control.HideSelection = false;
			this.Control.FullRowSelect = true;

			//Display vertical scrollbar
			ColumnHeader header = new ColumnHeader();
			header.Width = 300;

			this.Control.Columns.Add(header);
			this.Control.HeaderStyle = ColumnHeaderStyle.None;
			this.Control.View = View.Details;
		}
		#endregion

		#region Public Implementation
		/// <summary>
		/// Edits the specified object's value using the editor style indicated by the <see cref="M:System.Drawing.Design.UITypeEditor.GetEditStyle"></see> method.
		/// </summary>
		/// <param name="context">An <see cref="T:System.ComponentModel.ITypeDescriptorContext"></see> that can be used to gain additional context information.</param>
		/// <param name="provider">An <see cref="T:System.IServiceProvider"></see> that this editor can use to obtain services.</param>
		/// <param name="value">The object to edit.</param>
		/// <returns>
		/// The new value of the object. If the value of the object has not changed, this should return the same object it was passed.
		/// </returns>
		[PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")]
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods")]
		public override object EditValue(System.ComponentModel.ITypeDescriptorContext context, IServiceProvider provider, object value)
		{
			this.WindowsFormsEditorService = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));

			FillValues();

			this.WindowsFormsEditorService.DropDownControl(this.control);

			if(this.Control.SelectedItems.Count == 1)
			{
				value = this.Control.SelectedItems[0].Tag;
			}

			return value;
		}

		/// <summary>
		/// Gets the editor style used by the <see cref="M:System.Drawing.Design.UITypeEditor.EditValue(System.IServiceProvider,System.Object)"></see> method.
		/// </summary>
		/// <param name="context">An <see cref="T:System.ComponentModel.ITypeDescriptorContext"></see> that can be used to gain additional context information.</param>
		/// <returns>
		/// A <see cref="T:System.Drawing.Design.UITypeEditorEditStyle"></see> value that indicates the style of editor used by the <see cref="M:System.Drawing.Design.UITypeEditor.EditValue(System.IServiceProvider,System.Object)"></see> method. If the <see cref="T:System.Drawing.Design.UITypeEditor"></see> does not support this method, then <see cref="M:System.Drawing.Design.UITypeEditor.GetEditStyle"></see> will return <see cref="F:System.Drawing.Design.UITypeEditorEditStyle.None"></see>.
		/// </returns>
		[PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")]
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods")]
		public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
		{
			return UITypeEditorEditStyle.DropDown;
		}

		/// <summary>
		/// Gets a value indicating whether drop-down editors should be resizable by the user.
		/// </summary>
		/// <value></value>
		/// <returns>true if drop-down editors are resizable; otherwise, false. </returns>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase")]
		public override bool IsDropDownResizable
		{
			get
			{
				return true;
			}
		}
		#endregion

		#region Protected Implementation
		/// <summary>
		/// Fills the values.
		/// </summary>
		protected abstract void FillValues();

		/// <summary>
		/// Handles the SelectedIndexChanged event of the control control.
		/// </summary>
		/// <param name="sender">The source of the event.</param>
		/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers")]
		protected void ControlSelectedIndexChanged(object sender, EventArgs e)
		{
			this.WindowsFormsEditorService.CloseDropDown();
		}
		#endregion

		#region IDisposable Members
		/// <summary>
		/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
		/// </summary>
		public void Dispose()
		{
			Dispose(true);
			GC.SuppressFinalize(this);
		}

		/// <summary>
		/// Disposes the specified disposing.
		/// </summary>
		/// <param name="disposing">if set to <c>true</c> [disposing].</param>
		protected virtual void Dispose(bool disposing)
		{
			if(!this.disposed)
			{
				if(disposing)
				{
					this.Control.Dispose();
				}
			}
			disposed = true;
		}

		/// <summary>
		/// Releases unmanaged resources and performs other cleanup operations before the
		/// <see cref="ListViewEditorBase"/> is reclaimed by garbage collection.
		/// </summary>
		~ListViewEditorBase()
		{
			Dispose(false);
		}
		#endregion
	}
}